package jsyf.oa.serial;

import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * <B>系统名称：</B>序列化使用<BR>
 * <B>模块名称：</B><BR>
 * <B>中文类名：</B><BR>
 * <B>概要说明：</B><BR>
 *
 * @author: @韩武洽 @Wyshown
 * @Version: V1.0.0
 */
public class SerializationOptimizerImpl implements SerializationOptimizer {

    @Override
    public Collection<Class> getSerializableClasses() {
        List<Class> classes = new LinkedList<Class>();
        try {
            getClassesByPackageName("jsyf.oa.entity.email", classes);
            getClassesByPackageName("jsyf.oa.entity.system", classes);
            getClassesByPackageName("jsyf.oa.entity.wreport", classes);
            getClassesByPackageName("jsyf.oa.entity.apply", classes);
            getClassesByPackageName("jsyf.oa.entity.crm", classes);
        } catch (Exception e) {
            e.printStackTrace();
        }
       /*
        * 基本数据常量
        * */
        classes.add(Boolean.class);
        //这里可以把所有需要进行序列化的类进行添加
        classes.add(JSONObject.class);
        classes.add(List.class);
        classes.add(JSONArray.class);
        classes.add(Map.class);


        // Kryo fastjson序列化泛型扩展
        classes.add(GregorianCalendar.class);
        classes.add(InvocationHandler.class);
        classes.add(BigDecimal.class);
        classes.add(BigInteger.class);
        classes.add(Pattern.class);
        classes.add(BitSet.class);
        classes.add(URI.class);
        classes.add(UUID.class);
        classes.add(HashMap.class);
        classes.add(ArrayList.class);
        classes.add(LinkedList.class);
        classes.add(HashSet.class);
        classes.add(TreeSet.class);
        classes.add(Hashtable.class);
        classes.add(Date.class);
        classes.add(Calendar.class);
        classes.add(ConcurrentHashMap.class);
        classes.add(SimpleDateFormat.class);
        classes.add(Vector.class);
        classes.add(BitSet.class);
        classes.add(StringBuffer.class);
        classes.add(StringBuilder.class);
        classes.add(Object.class);
        classes.add(Object[].class);
        classes.add(String[].class);
        classes.add(byte[].class);
        classes.add(char[].class);
        classes.add(int[].class);
        classes.add(float[].class);
        classes.add(double[].class);

        /*classes.add(EmailMainEntity.class);
        classes.add(AttachModuleEntity.class);
        classes.add(AttachmentEntity.class);
        classes.add(EmailEntity.class);
        classes.add(EmailnboxEntity.class);
        classes.add(EmailReceiverEntity.class);
        classes.add(CompanyEntity.class);
        classes.add(DepartEntity.class);
        classes.add(RegionEntity.class);
        classes.add(RightEntity.class);
        classes.add(RoleEntity.class);
        classes.add(RoleRightEntity.class);
        classes.add(UserEntity.class);
        classes.add(UserRegionEntity.class);
        classes.add(UserRightEntity.class);
        classes.add(UserRoleEntity.class);
        classes.add(ModuleEntity.class);
        classes.add(Role2TemplateEntity.class);
        classes.add(Template2ModuleEntity.class);
        classes.add(TemplateEntity.class);
        classes.add(WReportBranchEntity.class);
        classes.add(WReportCostEntity.class);
        classes.add(WReportCusAndVistEntity.class);
        classes.add(WReportCustomerEntity.class);
        classes.add(WReportCusVisitEntity.class);
        classes.add(WReportDetailEntity.class);
        classes.add(WReportEntity.class);
        classes.add(WReportGatherEntity.class);
        classes.add(WReportMainEntity.class);
        classes.add(WReportUnfinishEntity.class);
        classes.add(WReportVieEntity.class);*/
        return classes;
    }

    /**
     * @param packageName
     * @Description: 添加某个文件夹下所有类  <br/>
     * @return: java.util.List<java.lang.Class>
     * @throw:
     * @author: 徐波
     * @createTime: 2017/11/20 0020 11:07
     * @Version: V1.0.0
     */
    private static List<Class> getClassesByPackageName(String packageName, List<Class> classes) throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<File>();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }
        for (File directory : dirs) {
            findClasses(directory, packageName, classes);
        }
        return classes;
    }


    /**
     * @param directory
     * @param packageName
     * @Description: 找到文件夹下的所有类并添加  <br/>
     * @return: java.util.List<java.lang.Class>
     * @throw:
     * @author: 徐波
     * @createTime: 2017/11/20 0020 11:09
     * @Version: V1.0.0
     */
    private static List<Class> findClasses(File directory, String packageName, List<Class> classes) throws Exception {
        if (!directory.exists()) {
            return classes;
        }

        File[] files = directory.listFiles();

        for (File file : files) {
            if (file.isDirectory()) {
                // 递归查找文件夹【即对应的包】下面的所有文件
//                assert !file.getName().contains(".");
//                classes.addAll(findClasses(file, packageName + '.'+ file.getName(),classes));
            } else if (file.getName().endsWith(".class")) {
                classes.add(Class.forName(packageName + "." + file.getName().substring(0, file.getName().length() - 6)));
            }
        }
        return classes;
    }
}
